using System;

using TrueCode.DependencyManager.BuildActions.Injection;


namespace TrueCode.DependencyManager.BuildActions.Instantiating
{
  public sealed class InstantiateByReflection : IInstantiate
  {
    #region IInstantiateBuildAction Members
    public void Execute( IBuildSession context )
    {
      if( context.Instance == null )
      {
        var type = context.SessionAim.Type;
        if( !type.IsInterface && !type.IsAbstract )
        {
          var constructorProvider = context.GetService< IConstructorProvider >();

          #region Assert that constructor provider is found
          if( constructorProvider == null )
          {
            var exception =
              new InvalidOperationException(
                "Constructor provider is not found. Please specify default one or specific for build aim" );
            exception.Data.Add( "Aim", context.SessionAim );
            throw exception;
          }
          #endregion

          var constructor = constructorProvider.GetConstructor( type );
          var parameters = constructor == null ? null : constructor.GetParameters();

          if( parameters == null || parameters.Length == 0 )
          {
            context.Instance = Activator.CreateInstance( type );
          }
          else
          {
            var parameterValueProvider = context.GetService< IParameterProvider >();
            context.Instance = Activator.CreateInstance( type,
                                                         parameterValueProvider.GetValuesFor( context,
                                                                                              constructor.GetParameters() ) );
          }
        }
      }
      context.ExecuteNextBuildAction();
    }
    #endregion
  }
}